home *** CD-ROM | disk | FTP | other *** search
- /*
- * copyfile.c - routines to copy a file from server to client
- */
- #include "RevRdist.h"
- #include "dispatch.h"
-
- void updateDesktop (CInfoPBRec *);
-
- static Longint lastflush = 0;
-
-
- /*
- *=========================================================================
- * copyFile (sp, cp, name) - copy file from server to client
- * entry: first param = pointer to catalog list node for server file
- * second param = pointer to catalog list node for client file
- * the information here is updated if the copy succeeds.
- * third param = name of client folder to get file
- *=========================================================================
- */
- DISPATCHED (copyFile)
- {
- #define COPYBUFSZ 16384
- struct lm
- {
- frame_t f;
- cnode_t * sp; /* copy of first arg */
- cnode_t * cp; /* copy of second arg */
- StringPtr name; /* copy of third arg */
- Ptr bufp; /* ptr to I/O buffer */
- HParamBlockRec src; /* param block for reading */
- HParamBlockRec dst; /* param block for writing */
- };
- typedef struct lm lm_t;
- register lm_t * m;
- Ptr bufp; /* temp copy of lm.bufp */
- OSErr error;
- Longint l; /* byte count */
- short result; /* our return value */
- Integer temp;
- CInfoPBRec cb; /* get/setCatInfo param block */
- Str255 cbuf; /* buffer for numeric conversions */
-
- m = *(lm_t **)fh;
- result = request;
- error = 0;
- switch (request)
- {
- case R_INIT:
- if (ClueID = resizeFrame (fh, sizeof (lm_t)))
- return R_ERROR;
- if ((bufp = NewPtr (COPYBUFSZ)) == nil)
- {
- if ((ClueID = MemError()) == 0)
- ClueID = memFullErr;
- return R_ERROR;
- }
- m = *(lm_t **)fh;
- m->sp = (cnode_t *)argv[0];
- m->cp = (cnode_t *)argv[1];
- m->name = (StringPtr)argv[2];
- m->bufp = bufp;
- m->f.state = 1;
- return R_CONT;
-
- case R_CONT:
- /*
- * Handle only the first step of R_CONT here, and the rest after
- * the request switch.
- */
- if (m->f.state == 1)
- {
- l = m->sp->in.f.fileLen + m->sp->in.f.rsrcLen;
- NumToString (l, cbuf);
- notice (L_COPYING, cbuf, m->sp->name, m->name, nil);
- m->f.state = 2;
- return R_CONT;
- }
- break;
-
- case R_BACKOUT:
- case R_QUIT:
- goto cleanexit;
- }
-
- /*
- * The body of the R_CONT code:
- */
- if (Flags & DB_LISTONLY)
- goto cleanexit;
- /*
- * Honor quit only if we are not the startup application, so that
- * we don't leave files missing if an antsy student cancels
- * an automatic RevRdist.
- */
- if (Quit && !(Flags & DB_STARTUP))
- goto cleanexit;
- switch (m->f.state)
- {
- case 2:
- /*
- * open the source file on the server.
- * if that succeeds, purge and create the client destination file.
- */
- m->src.fileParam.ioNamePtr = m->sp->name;
- m->src.fileParam.ioVRefNum = ServerVol;
- m->src.ioParam.ioPermssn = fsRdPerm;
- m->src.fileParam.ioDirID = m->sp->parID;
- error = PBHOpen (&m->src, false);
- if (error)
- {
- if (error == fnfErr)
- {
- notice (L_MISSING, m->sp->name, nil);
- goto cleanexit;
- }
- Clue1 = (SP) "\pPBHOpen";
- goto syserrexit;
- }
- if (m->cp->dirID)
- {
- /*
- * If the file already exists, delete it
- */
- error = discard (m->cp, false);
- if (error)
- {
- ClueID = error;
- if (error == fBsyErr)
- notice (E_FILE, m->cp->name, nil);
- else
- warning (E_FILE, m->cp->name, nil);
- goto cleanexit;
- }
- }
- m->dst.fileParam.ioNamePtr = m->cp->name;
- m->dst.fileParam.ioVRefNum = ClientVol;
- m->dst.fileParam.ioDirID = m->cp->parID;
- error = PBHCreate (&m->dst, false);
- if (error)
- {
- Clue1 = (SP) "\pPBHCreate";
- goto syserrexit;
- }
- /*
- * If the file has a data fork, set up to copy it.
- */
- if (m->sp->in.f.fileLen)
- {
- m->dst.ioParam.ioPermssn = fsRdWrPerm;
- error = PBHOpen (&m->dst, false);
- if (error)
- {
- Clue1 = (SP) "\pPBHOpen";
- goto syserrexit;
- }
- m->f.state = 3;
- }
- else
- {
- (void) PBClose ((ParmBlkPtr)&m->src, false);
- m->f.state = 4;
- }
- break;
-
- case 3:
- case 5:
- /*
- * copy one fork in COPYBUFSZ chunks
- */
- m->src.ioParam.ioBuffer = m->bufp;
- m->src.ioParam.ioReqCount = COPYBUFSZ;
- m->src.ioParam.ioActCount = 0;
- m->src.ioParam.ioPosMode = fsAtMark;
- error = PBRead ((ParmBlkPtr)&m->src, false);
- if ((l = m->src.ioParam.ioActCount) != 0)
- {
- m->dst.ioParam.ioBuffer = m->bufp;
- do
- {
- m->dst.ioParam.ioReqCount = l;
- m->dst.ioParam.ioActCount = 0;
- m->dst.ioParam.ioPosMode = fsAtMark;
- error = PBWrite ((ParmBlkPtr)&m->dst, false);
- if (error)
- break;
- l -= m->dst.ioParam.ioActCount;
- m->dst.ioParam.ioBuffer += m->dst.ioParam.ioActCount;
- } while (l > 0);
- if (error)
- {
- Clue1 = (SP) "\pPBWrite";
- goto syserrexit;
- }
- }
- else if (error && error != eofErr)
- {
- Clue1 = (SP) "\pPBRead";
- goto syserrexit;
- }
- else if (error == eofErr)
- {
- /*
- * one fork copy complete.
- */
- (void) PBClose ((ParmBlkPtr)&m->src, false);
- m->src.ioParam.ioRefNum = 0;
- error = PBClose ((ParmBlkPtr)&m->dst, false);
- m->dst.ioParam.ioRefNum = 0;
- if (error)
- {
- Clue1 = (SP) "\pPBClose";
- goto syserrexit;
- }
- m->f.state++;
- }
- break;
-
- case 4:
- /*
- * set up to copy resource fork
- * open source and destination forks
- */
- if (m->sp->in.f.rsrcLen == 0)
- {
- m->f.state = 6;
- break;
- }
- ZERO (m->src);
- m->src.fileParam.ioNamePtr = m->sp->name;
- m->src.fileParam.ioVRefNum = ServerVol;
- m->src.ioParam.ioPermssn = fsRdPerm;
- m->src.fileParam.ioDirID = m->sp->parID;
- error = PBHOpenRF (&m->src, false);
- if (error)
- {
- Clue1 = (SP) "\pPBHOpenRF";
- goto syserrexit;
- }
- ZERO (m->dst);
- m->dst.fileParam.ioNamePtr = m->cp->name;
- m->dst.fileParam.ioVRefNum = ClientVol;
- m->dst.ioParam.ioPermssn = fsRdWrPerm;
- m->dst.fileParam.ioDirID = m->cp->parID;
- error = PBHOpenRF (&m->dst, false);
- if (error)
- {
- Clue1 = (SP) "\pPBHOpenRF";
- goto syserrexit;
- }
- m->f.state++;
- break;
-
- case 6:
- /*
- * Both forks copied, copy Finder information
- */
- ZERO (cb);
- cb.hFileInfo.ioNamePtr = m->cp->name;
- cb.hFileInfo.ioVRefNum = ClientVol;
- cb.hFileInfo.ioDirID = m->cp->parID;
- error = PBGetCatInfo (&cb, false);
- if (error)
- {
- Clue1 = (SP) "\pPBGetCatInfo";
- goto syserrexit;
- }
- cb.hFileInfo.ioDirID = m->cp->parID;
- temp = cb.hFileInfo.ioFlFndrInfo.fdFldr;
- cb.hFileInfo.ioFlFndrInfo = m->sp->in.f.finfo;
- cb.hFileInfo.ioFlFndrInfo.fdFlags &= ~0x0010; /* clear inited bit */
- cb.hFileInfo.ioFlFndrInfo.fdFldr = temp;
- cb.hFileInfo.ioFlCrDat = m->sp->crDate;
- cb.hFileInfo.ioFlMdDat = m->sp->mdDate;
- error = PBSetCatInfo (&cb, false);
- if (error)
- {
- Clue1 = (SP) "\pPBSetCatInfo";
- goto syserrexit;
- }
- /*
- * If the file did not previously exist and it is an application,
- * update the Desktop file to know about it.
- */
- if (m->cp->dirID == 0
- && cb.hFileInfo.ioFlFndrInfo.fdType == 'APPL'
- && (cb.hFileInfo.ioFlFndrInfo.fdFlags & fHasBundle)
- )
- updateDesktop (&cb);
- saveCatInfo (&cb, m->cp);
- /*
- * Doing a Flush after every file slowed things down too much
- * on lots of small files, so we flush only every so often
- */
- l = TickCount ();
- if (l - lastflush > 60 * 20)
- {
- m->dst.fileParam.ioNamePtr = nil;
- error = PBFlushVol ((ParmBlkPtr)&m->dst, false);
- if (error)
- {
- Clue1 = (SP) "\pPBFlushVol";
- goto syserrexit;
- }
- lastflush = l;
- }
- goto cleanexit;
- }
- return result;
-
- syserrexit:
- ClueID = error;
- Clue2 = nil;
- warning (E_SYS, (SP) "\pcopyFile", nil);
- cleanexit:
- if (GetHandleSize ((Handle)fh) >= sizeof (lm_t))
- {
- if (m->dst.ioParam.ioRefNum)
- (void) PBClose ((ParmBlkPtr)&m->dst, false);
- if (m->src.ioParam.ioRefNum)
- (void) PBClose ((ParmBlkPtr)&m->src, false);
- if (error && m->f.state > 2)
- {
- ZERO (m->dst);
- m->dst.fileParam.ioNamePtr = m->cp->name;
- m->dst.fileParam.ioVRefNum = ClientVol;
- m->dst.fileParam.ioDirID = m->cp->parID;
- (void) PBHDelete (&m->dst, false);
- }
- if (m->bufp)
- DisposPtr (m->bufp);
- }
- if (! error)
- statMsgClr ();
- return (popCall (result, nil));
- }
-
-
-
- /*
- *=========================================================================
- * updateDesktop (cip) - update Finder Desktop file to know about new
- * application.
- * entry: cip = pointer to CInfoPBRec describing file
- * exit: Desktop updated (if possible)
- * errors are silently ignored
- *=========================================================================
- */
- void
- updateDesktop (cip)
- CInfoPBRec *cip;
- {
- struct applinfo
- {
- OSType creator; /* creator/owner id */
- Longint dirID; /* directory containing appl */
- /* char applname[]; /* file name */
- };
- typedef struct applinfo api_t;
-
- register OSType creator; /* application signature */
- register api_t * fp; /* pointer to ap info header */
- register Size len; /* temp byte length */
- register Size origlen; /* original resource size */
- register Ptr p, ep;
- static Handle hdl = 0; /* handle to APPL resource */
-
- if (hdl == 0)
- {
- /*
- * First call, get APPL resource
- */
- hdl = GetResource ('APPL', 0); /* see if available already */
- if (hdl == 0)
- {
- /*
- * Try to open Finder's Desktop file to find resource
- */
- Deskrefnum = OpenRFPerm((SP)"\pDesktop", ClientVol, fsRdWrPerm);
- if (Deskrefnum != -1)
- hdl = GetResource ('APPL', 0);
- }
- if (hdl == 0)
- {
- if (Deskrefnum != -1)
- {
- CloseResFile (Deskrefnum);
- Deskrefnum = -1;
- }
- hdl = (Handle) -1;
- return;
- }
- }
- else if (hdl == (Handle) -1)
- return;
- LoadResource (hdl);
- if (ResError())
- return;
- /*
- * Now, search the resource for an entry with a matching creator
- */
- creator = cip->hFileInfo.ioFlFndrInfo.fdCreator;
- origlen = SizeResource (hdl);
- for (p = *hdl, ep = p + origlen; p < ep; p += len)
- {
- fp = (api_t *)p;
- p = (Ptr) (fp+1); /* advance over header */
- len = (*p | 1) + 1; /* chars in name (rounded) */
- if (fp->creator == creator)
- {
- /*
- * Found it. If the containing directory has changed, update
- * the resource.
- */
- if (fp->dirID != cip->hFileInfo.ioFlParID)
- {
- fp->dirID = cip->hFileInfo.ioFlParID;
- ChangedResource (hdl);
- WriteResource (hdl);
- }
- return;
- }
- }
- /*
- * No matching signature in current APPL list.
- * Add one.
- */
- len = sizeof (api_t);
- p = (Ptr) cip->hFileInfo.ioNamePtr;
- len += (*p | 1) + 1;
- HUnlock (hdl);
- SetHandleSize (hdl, len + origlen);
- if (MemError())
- return;
- ep = *hdl + origlen;
- fp = (api_t *)ep;
- fp->creator = cip->hFileInfo.ioFlFndrInfo.fdCreator;
- fp->dirID = cip->hFileInfo.ioFlParID;
- ep = (Ptr) (fp+1);
- COPYPS (p, ep);
- if ((*ep & 1) == 0)
- ep[*ep + 1] = 0;
- ChangedResource (hdl);
- WriteResource (hdl);
- }